﻿using KBEngine;
using UnityEngine;
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;

public class UI : MonoBehaviour
{
    public static UI Instance;

    public string m_website = "127.0.0.1:10003";

    private List<string> m_playMsgs = new List<string>();
    private string m_labelMsg = string.Empty;
    private Color m_labelColor = Color.green;

    private int m_uiState;
    private string m_stringAccount;
    private string m_stringPasswd;

    private uint m_accountID;
    private string m_stringSession;
    private string m_stringToken;
    private List<GameServerInfo> m_uiServerList;
    private List<GameCharacterInfo> m_uiCharacters;

    private List<InstPlayerPreviewInfo> m_uiAvatars;
    private string m_stringCreateAvatarName;
    private bool m_isCreateAvatarMode;
    private uint m_selAvatarID;

    bool startRelogin = false;

    void Awake()
    {
        Instance = this;
        DontDestroyOnLoad(transform.gameObject);
        StartCoroutine(DBMgr.Instance.AsyncLoadDB());
    }

    void Start()
    {
        SceneManager.LoadScene("login");
    }

    void Update()
    {
        if (GameSession.Instance.IsRunning())
        {
            GameSession.Instance.Update();
        }
    }

    void OnDestroy()
    {
        GameSession.Instance.Dispose();
    }

    void onSelAvatarUI()
    {
        if (!m_isCreateAvatarMode && GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height - 40, 200, 30), "RemoveAvatar(删除角色)"))
        {
            if (m_selAvatarID == 0)
            {
                err("Please select a Avatar!(请选择角色!)");
            }
            else
            {
                info("Please wait...(请稍后...)");
                StartCoroutine(OnDeleteCharacter());
            }
        }

        if (!m_isCreateAvatarMode && GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height - 75, 200, 30), "CreateAvatar(创建角色)"))
        {
            m_isCreateAvatarMode = true;
        }

        if (!m_isCreateAvatarMode && GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height - 110, 200, 30), "EnterGame(进入游戏)"))
        {
            if (m_selAvatarID == 0)
            {
                err("Please select a Avatar!(请选择角色!)");
            }
            else
            {
                info("Please wait...(请稍后...)");
                GameSession.Instance.SendLoginCharacter(m_selAvatarID);
                m_uiState = 3;
                SceneManager.LoadScene("world");
                World.Instance.CreateHero();
            }
        }

        if (m_isCreateAvatarMode)
        {
            if (GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height - 40, 200, 30), "CreateAvatar-OK(创建完成)"))
            {
                if (m_stringCreateAvatarName.Length == 0)
                {
                    err("avatar name is null(角色名称为空)!");
                }
                else
                {
                    StartCoroutine(OnCreateCharacter());
                }
            }
            m_stringCreateAvatarName = GUI.TextField(new Rect(Screen.width / 2 - 100, Screen.height - 75, 200, 30), m_stringCreateAvatarName ?? string.Empty, 20);
        }

        if (m_uiAvatars != null && m_uiAvatars.Count > 0)
        {
            var oldColor = GUI.contentColor;
            for (int i = 0; i < m_uiAvatars.Count; ++i)
            {
                var instInfo = m_uiAvatars[i];
                if (instInfo.ipcInstID == m_selAvatarID)
                {
                    GUI.contentColor = Color.red;
                }
                if (GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height / 2 + 120 - 35 * i, 200, 30), instInfo.ipcNickName))
                {
                    m_selAvatarID = instInfo.ipcInstID;
                }
            }
            GUI.contentColor = oldColor;
        }
    }

    void onLoginUI()
    {
        if (GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height / 2 + 30, 200, 30), "Login(登陆)"))
        {
            if (m_stringAccount.Length > 0 && m_stringPasswd.Length > 5)
            {
                PlayerPrefs.SetString("AccountName", m_stringAccount);
                PlayerPrefs.SetString("AccountPasswd", m_stringPasswd);
                StartCoroutine(login());
            }
            else
            {
                err("account or password is error, length < 6!(账号或者密码错误，长度必须大于5!)");
            }
        }

        if (GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height / 2 + 70, 200, 30), "CreateAccount(注册账号)"))
        {
            if (m_stringAccount.Length > 0 && m_stringPasswd.Length > 5)
            {
                PlayerPrefs.SetString("AccountName", m_stringAccount);
                PlayerPrefs.SetString("AccountPasswd", m_stringPasswd);
                StartCoroutine(createAccount());
            }
            else
            {
                err("account or password is error, length < 6!(账号或者密码错误，长度必须大于5!)");
            }
        }

        if (m_stringAccount == null)
        {
            m_stringAccount = PlayerPrefs.GetString("AccountName", "");
        }
        if (m_stringPasswd == null)
        {
            m_stringPasswd = PlayerPrefs.GetString("AccountPasswd", "");
        }

        m_stringAccount = GUI.TextField(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 50, 200, 30), m_stringAccount, 20);
        m_stringPasswd = GUI.PasswordField(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 10, 200, 30), m_stringPasswd, '*');
    }

    void onSelServerUI()
    {
        GameServerInfo gsInfo = null;
        for (int i = 0; i < m_uiCharacters.Count; ++i)
        {
            var charInfo = m_uiCharacters[i];
            var displayName = string.Format("{0}:({1}){2}[{3}]",
                charInfo.ServerID, charInfo.CharacterID, charInfo.CharacterName, charInfo.CharacterLevel);
            if (GUI.Button(new Rect(Screen.width / 2 - 100, 150 + 30 * i, 200, 30), displayName))
            {
                foreach (var gsCurInfo in m_uiServerList)
                {
                    if (gsCurInfo.ID == charInfo.ServerID)
                    {
                        gsInfo = gsCurInfo;
                        break;
                    }
                }
                if (gsInfo == null)
                {
                    err(String.Format("game server {0} isn't exist.", charInfo.ServerID));
                }
            }
        }
        for (int i = 0; i < m_uiServerList.Count; ++i)
        {
            var gsCurInfo = m_uiServerList[i];
            var gsCurName = gsCurInfo.LogicName != "" ? gsCurInfo.LogicName : string.Format("服务器{0}", gsCurInfo.ID);
            if (GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 30 * i, 200, 30), gsCurName))
            {
                gsInfo = gsCurInfo;
            }
        }
        if (gsInfo != null)
        {
            StartCoroutine(PlayGame(gsInfo.ExternalIP, gsInfo.ExternalPort, gsInfo.LogicId != 0 ? gsInfo.LogicId : gsInfo.ID));
        }
    }

    void onWorldUI()
    {
        var hero = World.Instance.Hero;
        if (hero != null)
        {
            if (hero.IsDead())
            {
                if (GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height / 2, 200, 30), "Relive(复活)"))
                {
                    GameSession.Instance.SendPlayerRevive();
                }
            }
            GUI.Label(new Rect(Screen.width / 2 - 150, 20, 400, 100),
                string.Format("ID[{0},{1}],POS[{2}],DIR[{3}]", hero.GetGuid().SID, hero.GetGuid().UID,
                hero.transform.position.ToString(), hero.transform.eulerAngles.ToString()));
            if (GUI.Button(new Rect(Screen.width - 70, Screen.height - 35, 30, 30), "2"))
            {
                var obj = World.Instance.GetObjectController(hero.TargetGuid);
                var dir = obj != null ? obj.Position - hero.Position : hero.Direction;
                GameSession.Instance.SendSpellCast(2, hero.TargetGuid, hero.Position, dir);
            }
            if (GUI.Button(new Rect(Screen.width - 35, Screen.height - 35, 30, 30), "3"))
            {
                var obj = World.Instance.GetObjectController(hero.TargetGuid);
                var dir = obj != null ? obj.Position - hero.Position : hero.Direction;
                GameSession.Instance.SendSpellCast(3, hero.TargetGuid, hero.Position, dir);
            }
        }
    }

    void OnGUI()
    {
        switch (m_uiState)
        {
            case 0:
                onLoginUI();
                break;
            case 1:
                onSelServerUI();
                break;
            case 2:
                onSelAvatarUI();
                break;
            case 3:
                onWorldUI();
                break;
            default:
                Debug.Assert(false);
                break;
        }

        GUI.contentColor = m_labelColor;
        GUI.Label(new Rect((Screen.width / 2) - 100, 40, 400, 100), m_labelMsg);

        for (int i = 0, n = m_playMsgs.Count; i < n; ++i)
        {
            GUI.Label(new Rect(0, Screen.height - 30 - 20 * i, 400, 20), m_playMsgs[i]);
        }
    }

    public void err(string s)
    {
        m_labelColor = Color.red;
        m_labelMsg = s;
    }

    public void info(string s)
    {
        m_labelColor = Color.green;
        m_labelMsg = s;
    }

    public void PushPlayMsg(string s)
    {
        m_playMsgs.Insert(0, s);
        if (m_playMsgs.Count > 20)
        {
            m_playMsgs.RemoveAt(m_playMsgs.Count - 1);
        }
    }

    class HTTPRegisterAccountResp : HTTPRespBase
    {
        public UInt32 AccountID;
    }

    public IEnumerator createAccount()
    {
        info("connect to login server...(连接到登陆服务端...)");

        var formData = new WWWForm();
        formData.AddField("account", m_stringAccount);
        formData.AddField("password", m_stringPasswd);
        var url = String.Format("https://{0}/RegisterAccount.html", m_website);
        using (var webRequest = UnityWebRequest.Post(url, formData))
        {
            webRequest.certificateHandler = new AcceptAllCertificates();
            yield return webRequest.SendWebRequest();
            if (webRequest.isNetworkError || webRequest.isHttpError)
            {
                err("createAccount is error(注册账号错误)! err=" + webRequest.error);
                yield break;
            }
            var text = webRequest.downloadHandler.text;
            var resp = JsonUtility.FromJson<HTTPRegisterAccountResp>(text);
            if (resp.error != 0)
            {
                err("createAccount is error(注册账号错误)! err=" + resp.message);
                yield break;
            }
            info("createAccount is successfully!(注册账号成功!)");
            Debug.Log("accountID:" + resp.AccountID);
        }
    }

    class HTTPVerifyAccountResp : HTTPRespBase
    {
        public UInt32 AccountID;
        public UInt32 LastLogicGsId;
        public string Session;
        public string Token;
    }

    class HTTPGetAccountCharatersResp : HTTPRespBase
    {
        public List<GameCharacterInfo> CharacterInfos = new List<GameCharacterInfo>();
    }

    class HTTPGetServerListResp : HTTPRespBase
    {
        public List<GameServerInfo> ServerList = new List<GameServerInfo>();
    }

    private IEnumerator login()
    {
        info("connect to login server...(连接到登陆服务端...)");

        var formData = new WWWForm();
        formData.AddField("account", m_stringAccount);
        formData.AddField("password", m_stringPasswd);
        var url = String.Format("https://{0}/VerifyAccount.html", m_website);
        using (var webRequest = UnityWebRequest.Post(url, formData))
        {
            webRequest.certificateHandler = new AcceptAllCertificates();
            yield return webRequest.SendWebRequest();
            if (webRequest.isNetworkError || webRequest.isHttpError)
            {
                err("login is failed(登陆失败), error: " + webRequest.error);
                yield break;
            }
            var text = webRequest.downloadHandler.text;
            var resp = JsonUtility.FromJson<HTTPVerifyAccountResp>(text);
            if (resp.error != 0)
            {
                err("login is failed(登陆失败), error: " + resp.message);
                yield break;
            }
            info("login is successfully!(登陆成功!)");
            m_accountID = resp.AccountID;
            m_stringSession = resp.Session;
            m_stringToken = resp.Token;
        }

        url = String.Format("https://{0}/GetServerList.html", m_website);
        using (var webRequest = UnityWebRequest.Post(url, formData))
        {
            webRequest.certificateHandler = new AcceptAllCertificates();
            yield return webRequest.SendWebRequest();
            if (webRequest.isNetworkError || webRequest.isHttpError)
            {
                err("getServerList is failed(获取服务器列表失败), error: " + webRequest.error);
                yield break;
            }
            var text = webRequest.downloadHandler.text;
            var resp = JsonUtility.FromJson<HTTPGetServerListResp>(text);
            if (resp.error != 0)
            {
                err("getServerList is failed(获取服务器列表失败), error: " + resp.message);
                yield break;
            }
            info("getServerList is successfully!(获取服务器列表成功!)");
            m_uiServerList = resp.ServerList;
        }

        formData = new WWWForm();
        formData.AddField("session", m_stringSession);
        formData.AddField("gsid", 0);
        url = String.Format("https://{0}/GetAccountCharaters.html", m_website);
        using (var webRequest = UnityWebRequest.Post(url, formData))
        {
            webRequest.certificateHandler = new AcceptAllCertificates();
            yield return webRequest.SendWebRequest();
            if (webRequest.isNetworkError || webRequest.isHttpError)
            {
                err("getCharaters is failed(获取角色列表失败), error: " + webRequest.error);
                yield break;
            }
            var text = webRequest.downloadHandler.text;
            var resp = JsonUtility.FromJson<HTTPGetAccountCharatersResp>(text);
            if (resp.error != 0)
            {
                err("getCharaters is failed(获取角色列表失败), error: " + resp.message);
                yield break;
            }
            info("getCharaters is successfully!(获取角色列表成功!)");
            m_uiCharacters = resp.CharacterInfos;
        }

        m_uiState = 1;
        SceneManager.LoadScene("selservers");
    }

    public IEnumerator PlayGame(string host, UInt16 port, UInt32 gsID)
    {
        info("connect to game server...(连接到游戏服务端...)");

        GameSession.Instance.ConnectServer(host, port);
        yield return new WaitGameSessionConnecting();
        if (!GameSession.Instance.IsRunning())
        {
            err("connect game server(" + host + ":" + port + ") is error! (连接错误)");
            yield break;
        }
        info("connect game server successfully, please wait...(连接成功，请等候...)");

        GameSession.Instance.SendMmorpgLogin(gsID, m_accountID, m_stringToken);
        var gsAwaitResp = new WaitGameSessionPacketResp(GAME_OPCODE.SMSG_MMORPG_LOGIN_RESP);
        yield return gsAwaitResp;
        if (!GameSession.Instance.IsRunning())
        {
            err("disconnect game server! (断开游戏连接)");
            yield break;
        }
        var pck = gsAwaitResp.resp;
        pck.Read(out uint accountID);
        pck.Read(out int errCode);
        pck.Read(out string errMsg);
        if (errCode != 0)
        {
            err(errMsg);
            yield break;
        }

        yield return StartCoroutine(GetCharacterList());

        m_uiState = 2;
        SceneManager.LoadScene("selavatars");
    }

    public IEnumerator GetCharacterList()
    {
        GameSession.Instance.SendGetCharacterList();
        var gsAwaitResp = new WaitGameSessionPacketResp(GAME_OPCODE.SMSG_CHARACTER_LIST_RESP);
        yield return gsAwaitResp;
        if (!GameSession.Instance.IsRunning())
        {
            err("disconnect game server! (断开游戏连接)");
            yield break;
        }
        m_uiAvatars = new List<InstPlayerPreviewInfo>();
        var pck = gsAwaitResp.resp;
        while (!pck.IsReadableEmpty())
        {
            BinaryHelper.LoadFromBuffer(out InstPlayerPreviewInfo instInfo, pck);
            m_uiAvatars.Add(instInfo);
        }
    }

    public IEnumerator OnCreateCharacter()
    {
        GameSession.Instance.SendCreateCharacter(m_stringCreateAvatarName);
        var gsAwaitResp = new WaitGameSessionPacketResp(GAME_OPCODE.SMSG_CHARACTER_CREATE_RESP);
        yield return gsAwaitResp;
        if (!GameSession.Instance.IsRunning())
        {
            err("disconnect game server! (断开游戏连接)");
            yield break;
        }
        var pck = gsAwaitResp.resp;
        pck.Read(out int errCode);
        if (errCode != 0)
        {
            err("Create player failed, error: " + errCode + "! (创建角色失败)");
            yield break;
        }
        info("Create player successfully! (创建角色成功)");
        m_stringCreateAvatarName = string.Empty;

        yield return StartCoroutine(GetCharacterList());
        m_isCreateAvatarMode = false;
    }

    public IEnumerator OnDeleteCharacter()
    {
        GameSession.Instance.SendDeleteCharacter(m_selAvatarID);
        var gsAwaitResp = new WaitGameSessionPacketResp(GAME_OPCODE.SMSG_CHARACTER_DELETE_RESP);
        yield return gsAwaitResp;
        if (!GameSession.Instance.IsRunning())
        {
            err("disconnect game server! (断开游戏连接)");
            yield break;
        }
        var pck = gsAwaitResp.resp;
        pck.Read(out int errCode);
        if (errCode != 0)
        {
            err("Delete player failed, error: " + errCode + "! (删除角色失败)");
            yield break;
        }
        info("Delete player successfully! (删除角色成功)");
        m_selAvatarID = 0;

        yield return StartCoroutine(GetCharacterList());
    }

    public void onLoginBaseappFailed(UInt16 failedcode)
    {
        err("loginBaseapp is failed(登陆网关失败), err=" + KBEngineApp.app.serverErr(failedcode));
    }

    public void onLoginBaseapp()
    {
        info("connect to loginBaseapp, please wait...(连接到网关， 请稍后...)");
    }

    public void onReloginBaseappFailed(UInt16 failedcode)
    {
        err("relogin is failed(重连网关失败), err=" + KBEngineApp.app.serverErr(failedcode));
        startRelogin = false;
    }

    public void onReloginBaseappSuccessfully()
    {
        info("relogin is successfully!(重连成功!)");
        startRelogin = false;
    }



    public void onKicked(UInt16 failedcode)
    {
        err("kick, disconnect!, reason=" + KBEngineApp.app.serverErr(failedcode));
        m_uiState = 0;
        SceneManager.LoadScene("login");
    }

    public void Loginapp_importClientMessages()
    {
        info("Loginapp_importClientMessages ...");
    }

    public void Baseapp_importClientMessages()
    {
        info("Baseapp_importClientMessages ...");
    }

    public void Baseapp_importClientEntityDef()
    {
        info("importClientEntityDef ...");
    }

    //public void onReqAvatarList(Dictionary<UInt64, AVATAR_INFOS> avatarList)
    //{
    //    ui_avatarList = avatarList;
    //}

    //public void onCreateAvatarResult(UInt64 retcode, AVATAR_INFOS info, Dictionary<UInt64, AVATAR_INFOS> avatarList)
    //{
    //    if (retcode != 0)
    //    {
    //        err("Error creating avatar, errcode=" + retcode);
    //        return;
    //    }

    //    onReqAvatarList(avatarList);
    //}

    //public void onRemoveAvatar(UInt64 dbid, Dictionary<UInt64, AVATAR_INFOS> avatarList)
    //{
    //    if (dbid == 0)
    //    {
    //        err("Delete the avatar error!(删除角色错误!)");
    //        return;
    //    }

    //    onReqAvatarList(avatarList);
    //}

    public void onDisconnected()
    {
        err("disconnect! will try to reconnect...(你已掉线，尝试重连中!)");
        startRelogin = true;
        Invoke("onReloginBaseappTimer", 1.0f);
    }

    public void onReloginBaseappTimer()
    {
        if (m_uiState == 0)
        {
            err("disconnect! (你已掉线!)");
            return;
        }

        KBEngineApp.app.reloginBaseapp();

        if (startRelogin)
            Invoke("onReloginBaseappTimer", 3.0f);
    }
}
